/**
 * edurender
 * test_main.c
 * (c) 2009 J. Brad Byrd
 */

#include "test_window.h"

#include "../../src/er/er_math.h"

#include <assert.h>
#include <math.h>

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#pragma warning(disable : 4100) // No "unreferenced formal parameter" warnings in this file.

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
	LPSTR lpCmdLine, int showCmd)
{
	ERContext context;
	
	ERfloat triVerts[] =
	{

		 0.0f,  1.0f, 0,
		 1.0f, -1.0f, 0,
		-1.0f, -1.0f, 0,

/*
		 0.0f,  1.0f, 0,
		-1.0f, -1.0f, 0,
		 1.7f, -1.6f, 0,
*/
/*
		 0.0f,  0.3f, -5.0f,
		-0.5f, -0.3f, 0,
		 0.2f, -0.5f, 0.25f,
*/

/*
		 1, 0, -5,
		-1, 0, -5,
		 0, -.25f, -2,
*/

/*
		 0, 0, -5,
		-.4f, -.5f, -2,
		 .4f, -.5f, -2,
*/
	};

	ERfloat quadVerts[] =
	{
		-1.0f, -1.0f, 0,
		 1.0f, -1.0f, 0,
		 1.0f,  1.0f, 0,
		-1.0f,  1.0f, 0,
	};
	
	ERfloat quadTexCoords[] =
	{
		0.0f, 0.0f,
		1.0f, 0.0f,
		1.0f, 1.0f,
		0.0f, 1.0f,
	};
	
	ERfloat stripVerts[] =
	{
		-1.0f, -1.0f, 0,
		 1.0f, -1.0f, 0,
		-1.0f,  1.0f, 0,
		 1.0f,  1.0f, 0,
	};
	
	ERuint check[] = 
	{
		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0000FFFF,
		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
		0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F,
		0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
		0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
		0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
		0x0000FFFF, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
	};
	
	ERfloat fovy = 3.1415926f / 3.0f;
	ERfloat aspect = 800.0f / 600.0f;
	ERfloat znear = 1.0f;
	ERfloat zfar = 1000.0f;
	
	ERfloat yscale = cosf(fovy * 0.5f) / sinf(fovy * 0.5f);
	ERfloat xscale = yscale / aspect; 
	ERfloat zdenom = 1.0f / (znear - zfar);
	
	ERMatrix4x4f proj;
	ERMatrix4x4f cam;

	ERTexture2D texture;

	//ERVector3f eye = {0, 0, 2};
	ERVector3f eye = {0, -1.25f, 1.25f};
	//ERVector3f eye = {0, 0, 0};
	//ERVector3f eye = {0, 0, -1};
	ERVector3f center = {0, 0, 0};
	ERVector3f up = {0, 1, 0};

	ERVector3f f, s, u;

	int frame = 0;

	proj._00 = xscale;  proj._01 =      0;  proj._02 = 0;                        proj._03 = 0;
	proj._10 =      0;  proj._11 = yscale;  proj._12 = 0;                        proj._13 = 0;
	proj._20 =      0;  proj._21 =      0;  proj._22 = (zfar + znear) * zdenom;  proj._23 = (2.0f * znear * zfar) * zdenom;
	proj._30 =      0;  proj._31 =      0;  proj._32 = -1;                       proj._33 = 0;
	
	if (erInitialize() != ER_RESULT_OK)
		assert(0);

	testCreateWindowAndContext("Edurender Test", 800, 600, &context);

	erSetMatrix(context, ER_MATRIX_PROJECTION, ER_MATRIX_STORAGE_ROW_MAJOR, &proj._00);
	//erSetPositionArray(context, sizeof(ERfloat) * 3, triVerts);
	erSetPositionArray(context, sizeof(ERfloat) * 3, quadVerts);
	//erSetPositionArray(context, sizeof(ERfloat) * 3, stripVerts);

	erSetTexCoordArray(context, sizeof(ERfloat) * 2, quadTexCoords, 0);

	erCreateTexture2D(context, 8, 8, ER_FORMAT_RGBA8, &texture);
	erUploadTexture2D(context, texture, 0, check);
	erSetTexture(context, 0, texture);

	while (testPumpWindow())
	{
		float cs = cosf((float)frame * 0.01f);
		float sn = sinf((float)frame * 0.01f);

		ERMatrix4x4f mv;
		ERMatrix4x4f rot;
		ERMatrix4x4f trans;
		
		//eye.z = (sinf((float)frame * 0.005f)) * 3.0f;// + 2.0f;
		//eye.x = (sinf((float)frame * 0.005f)) * -5.0f;// + 2.0f;
		//eye.y = (sinf((float)frame * 0.005f)) * -4.0f;

		eye.y = (cosf((float)frame * 0.01f)) * -1.25f;
		eye.z = 2.0f;

		erSub3(&f, &center, &eye);
		erNormalize3(&f, &f);
		erCross3(&s, &f, &up);
		erCross3(&u, &s, &f);
		
		cam._00 =  s.x;  cam._01 =  s.y;  cam._02 =  s.z;  cam._03 = 0;
		cam._10 =  u.x;  cam._11 =  u.y;  cam._12 =  u.z;  cam._13 = 0;
		cam._20 = -f.x;  cam._21 = -f.y;  cam._22 = -f.z;  cam._23 = 0;
		cam._30 =    0;  cam._31 =    0;  cam._32 =    0;  cam._33 = 1;

		erIdentityMatrix(&trans);
		trans._03 = -eye.x;
		trans._13 = -eye.y;
		trans._23 = -eye.z;

		erIdentityMatrix(&rot);
		rot._00 = cs;
		rot._02 = -sn;
		rot._20 = sn;
		rot._22 = cs;

		erIdentityMatrix(&mv);

		erMulMatrix(&mv, &mv, &cam);
		erMulMatrix(&mv, &mv, &trans);
		//erMulMatrix(&mv, &mv, &rot);

		erSetMatrix(context, ER_MATRIX_MODELVIEW, ER_MATRIX_STORAGE_ROW_MAJOR, &mv._00);
		erClearColorBuffer(context, 0.0f, 0.0f, 0.0f, 1.0f);
		//erDraw(context, ER_PRIMITIVE_TRIANGLES, 3, 0);
		erDraw(context, ER_PRIMITIVE_QUADS, 4, 0);
		//erDraw(context, ER_PRIMITIVE_TRIANGLE_STRIP, 4, 0);
		erSwapBuffers(context);
		
		frame++;
	}

	erShutdown();
	
	return 0;
}
